/* 三国志2整合脚本(UTF-8 with BOM),一键下上A,一键马上挑人,一键后跳踢,一键滑步升龙,一键暂停,一键切换静音
  根据运行模拟器的不同按键有区别,目前包括WinKawaks和游聚平台两种模式.
  Gui相关函数可以设定,但还是需要是全局函数,绑定全局变量,即使尝试绑定class中的变量其实也是换了个全局变量名称,无意义,所以不用class了.
  
  By setycyas @2022-11-02
*/

/* 全局设定 
*/ { ;不缩进块
#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
} ;不缩进块

/* 调用库
*/ { ;不缩进块
#Include ..\MyAhkModules\MyKey.ahk ;按键相关库,所有函数导出到MyKey对象中
} ;不缩进块

/* 全局变量
*/ { ;不缩进块
  
;常量,全体大写
KEY_PUNCH := "d" ;拳按键
KEY_JUMP := "e" ;跳按键

;枚举量,也属于常量,全体大写
;出招时面向左,右
FACE_LEFT := 0 
FACE_RIGHT := 1 
;马上挑人砸向左,右
THROW_LEFT := 0
THROW_RIGHT := 1
;模式枚举量
MODE_NORMAL := 0 ;一般模式
MODE_ZHAOYUN := 1 ;赵云模式
MODE_HORSE := 2 ;马战模式
MODE_TOGGLE := 3 ;不是一种模式,在函数中表示模式切换,同时表示模式数量 
;模式对应的颜色枚举量
MODE_COLOR_NORMAL = E0E0E0
MODE_COLOR_ZHAOYUN = 00A0D8
MODE_COLOR_HORSE = B87040

;变量
exeTitle := "" ;接收游戏平台选择
sbHWND := "" ;用于指定statusBar,其实只是用变量名做句柄而已
mode := MODE_NORMAL ;当前模式
duDuration1 := 70 ;↓↑A当中按↓的时长
duDelay1 := 20 ;↓↑A延时1,定义为按↓结束到按↑的毫秒数
duDelay2 := 80 ;↓↑A延时1延时2,定义为按↑开始到按A的毫秒数
horseDelay := 50 ;马上挑人技能延时,定义为按↑A并放手后到按方向键的毫秒数,测试发现:魏延赵云50,关羽100,张飞150
backJumpDelay := 50 ;后跳踢延时,定义为按B键后再按方向键的毫秒数,测试发现50对关羽之外的角色都可以,但关羽怎么设定都不一定成功

} ;不缩进块

/* 游戏操作相关函数
*/ { ;不缩进块

;缩短MyKey.press函数名称
press(key, pressDuration := 100){
  global
  return MyKey.press.Call(key, pressDuration)
}

;缩短MyKey的pressKeys函数名
pressKeys(keys, delays, duration := 50){
  global
  return MyKey.pressKeys.Call(keys, delays, duration)
}

;切换模式,_mode参数是模式枚举量MODE_的其中一个,表示切换到该模式,但MODE_TOGGLE表示的是切换模式
changeMode(_mode){
  global
  
  ;令mode获得正确的模式
  if (_mode == MODE_TOGGLE) {
    mode := Mod(mode+1, MODE_TOGGLE) 
  } else {
    mode := _mode
  }
  ;在状态栏显示当前模式并转换颜色,多窗口下用SB_SetText效果不行无法指定窗口,只能把状态栏当作一般组件用GuiControl指令
  if (mode == MODE_NORMAL) {
    ;SB_SetText("一般模式")
    GuiControl, MainUI:Text, sbHWND, 一般模式
    Gui, MainUI:Color, %MODE_COLOR_NORMAL%
  } else if (mode == MODE_ZHAOYUN) {
    ;SB_SetText("赵云模式")
    GuiControl, MainUI:Text, sbHWND, 赵云模式
    Gui, MainUI:Color, %MODE_COLOR_ZHAOYUN%
  } else if (mode == MODE_HORSE) {
    ;SB_SetText("马战模式")
    GuiControl, MainUI:Text, sbHWND, 马战模式
    Gui, MainUI:Color, %MODE_COLOR_HORSE%
  }
}

;↓↑A技能,按下后立即按方向键可使出赵云的带方向升龙剑
duSkill(){
  global
  
  press("down", duDuration1)
  sleep, %duDelay1%
  pressKeys(["up", KEY_PUNCH], [duDelay2], 50)
}

;↓→↑A技能,指定面向方向,枚举量FACE_的其中一个
dfuSkill(face){
  global
  
  local direction := "left"
  if (face != FACE_LEFT)
    direction := "right"
  
  press("down", duDuration1)
  sleep, %duDelay1%
  pressKeys([direction, "up", KEY_PUNCH], [50, duDelay2], 50)
}

;←→A技能,可设定出招方向,枚举量FACE_的其中一个,骑马才能用,测试发现左右需要的参数和操作细节有不同
lrSkill(face){
  global
  
  if (face == FACE_LEFT) {
    ; pressKeys(["right", "left"], [100], 70)
    press("right", 100)
    pressKeys(["left", KEY_PUNCH], [100], 50)
    ;press(KEY_PUNCH, 50)
  } else {
    press("left", 150)
    pressKeys(["right", KEY_PUNCH], [100], 50)
  }
}

;↑A+方向,马上挑人技能,可指定方向是扔到左还是右,枚举量THROW_的其中一个
u1HorseSkill(throw_){
  global

  local direction := "left"
  if (throw_ != THROW_LEFT) {
    direction := "right"
  }

  ;pressKeys(["up", KEY_PUNCH], [50], 70)
  pressKeys(["down", KEY_PUNCH], [50], 70)
  ;press(KEY_PUNCH, 70)
  sleep, %horseDelay%
  press(direction, 70)
}

;后跳踢,指定面向方向,枚举量FACE_的其中一个
backJumpKick(face){
  global
  
  local direction := "right"
  if (face != FACE_LEFT)
    direction := "left"
  pressKeys([KEY_JUMP, direction], [backJumpDelay], 70)
  sleep, 50
  press(KEY_PUNCH, 70)
}

;梅花大坐,指定面向方向,枚举量FACE_的其中一个
;失败...
bigSit(face){
  global
  
  local direction1 := "left"
  local direction2 := "right"
  local delay := 30
  
  if (face != FACE_RIGHT) {
    direction1 := "right"
    direction2 := "left"
  }
  ;MyKey.inputSkill.call([direction1, "down", direction2, "up", direction1, KEY_PUNCH], [20, 20, 20, 20, 20, 20])
  MyKey.inputSkill.call(["down", direction2, "up", direction1, KEY_PUNCH], [50, 50, 50, 50, 50])
}

;吃包子一次,使用时需多次调用
eatBread(){
  global
  
  pressKeys(["down", KEY_PUNCH], [20], 20)
  pressKeys(["right", KEY_PUNCH], [20], 20)
  pressKeys(["up", KEY_PUNCH], [20], 20)
  pressKeys(["left", KEY_PUNCH], [20], 20)
}

} ;不缩进块

/* 设置UI的函数 
*/ { ; 不缩进块

;选择游戏平台的UI
selectionUI(){
  Gui, New, , 选择游戏平台
  Gui, add, ListBox, vexeTitle Choose1, WinKawaks.exe|X-Zone.exe
  Gui, add, Button, gButtonTitleSelect, 选择游戏平台
  Gui, show
}    

;设置游戏的主要UI
setupUI(title) {
  global
  
  Gui, MainUI:New, , %title% - 三国志2
  Gui, Add, Tab3, w250, 参数设定|热键-一般模式|热键-赵云模式|热键-马战模式| ;顺便测试标签页分组,下面直接加入的组件属于当前标签页
  Gui, Tab, 1 ;表示以下组件属于第1个标签页,可省略
  Gui, Add, Text, x+20 y+20, ↓↑A持续1： ;
  Gui, Add, Edit, xp+80 yp-3 w60 vduDuration1, %duDuration1% ;按键持续时间
  Gui, Add, Text, xp-80 yp+30, ↓↑A延时1： ;
  Gui, Add, Edit, xp+80 yp-3 w60 vduDelay1, %duDelay1% ;技能↓↑A延时1
  Gui, Add, Text, xp-80 yp+30, ↓↑A延时2： ;
  Gui, Add, Edit, xp+80 yp-3 w60 vduDelay2, %duDelay2% ;技能↓↑A延时2
  Gui, Add, Text, xp-80 yp+30, 马上挑人延时： ;
  Gui, Add, Edit, xp+80 yp-3 w60 vhorseDelay, %horseDelay% ;马上挑人技能延时
  Gui, Add, Text, xp-80 yp+30, 后跳踢延时： ;
  Gui, Add, Edit, xp+80 yp-3 w60 vbackJumpDelay, %backJumpDelay% ;后跳踢延时
  Gui, Tab, 2 ;表示以下组件属于第2个标签页
  Gui, Add, Text, ,s - ↓↑a
  Gui, Add, Text, ,q - ↓b
  Gui, Add, Text, ,r - ↓b后接↓↑a
  Gui, Add, Text, ,2`,3 - 面向右,左后跳踢
  Gui, Tab, 3 ;表示以下组件属于第3个标签页
  Gui, Add, Text, ,s - ↓↑a
  Gui, Add, Text, ,q - 面向左边滑步升龙
  Gui, Add, Text, ,r - 面向右边滑步升龙
  Gui, Add, Text, ,2`,3 - 面向右左后跳踢
  Gui, Tab, 4 ;表示以下组件属于第4个标签页
  Gui, Add, Text, ,q - 向左挑人
  Gui, Add, Text, ,r - 向右挑人
  Gui, Add, Text, ,s - 单发一般攻击
  Gui, Add, Text, ,2`,3 - 面向右左←→a
  Gui, Tab ;表示下面组件不再属于标签页
  Gui, Add, Text, ,RControl - 切换模式
  if (title == "WinKawaks.exe") {
    Gui, Add, Text, ,numpad0 - 切换暂停与开始
  }
  Gui, Add, Text, ,numpad1 - 切换静音
  Gui, Add, Button, gButtonSubmit_, 提交 ;提交,运行ButtonSubmit_()函数
  Gui, Add, Button, xp+120 gButtonExit, 退出 ;结束app
  Gui, Add, StatusBar, vsbHWND ;状态栏,用变量名指定句柄
  Gui, MainUI:+AlwaysOnTop
  Gui, MainUI:Show, w280h330
}

} ;不缩进块

/* Gui响应函数
*/ { ;不缩进块

ButtonSubmit_(){
  Gui, Submit, NoHide ; 保存用户输入后每个控件的数据,NoHide可以在提交数据后保持窗体显示
  MsgBox, You have submit your changes!
}

ButtonExit(){
  ExitApp
}

;只能用在不设定名字的Gui,所以两个Gui只有一个生效,我选择了让启动时的那个生效
GuiClose(){
  ExitApp
}

;选择游戏平台后的操作
ButtonTitleSelect(){
  global
  
  Gui, Submit, Hide
  Gui, selectionUI:Destroy
  setupUI(exeTitle)
  setupHotkeys(exeTitle)
  changeMode(mode)
}

} ;不缩进块

/* 快捷键响应函数
*/ { ;不缩进块
;s键,↓↑a必杀,上马后换成一般攻击键
KeyS(){
  global
  
  if ((mode == MODE_ZHAOYUN) or (mode == MODE_NORMAL)) {
    duSkill()
  } else if (mode == MODE_HORSE) {
    press(KEY_PUNCH, 70)
  }
}

;q键
KeyQ(){
  global
  
  if (mode == MODE_HORSE) {
    u1HorseSkill(THROW_LEFT)
  } else if (mode == MODE_ZHAOYUN) {
    dfuSkill(FACE_LEFT)
  } else if (mode == MODE_NORMAL) {
    pressKeys(["down", KEY_JUMP], [50])
  }
}

;r键
KeyR(){
  global
  
  if (mode == MODE_HORSE) {
    u1HorseSkill(THROW_RIGHT)
  } else if (mode == MODE_ZHAOYUN) {
    dfuSkill(FACE_RIGHT)
  } else if (mode == MODE_NORMAL) {
    pressKeys(["down", KEY_JUMP], [50])
    sleep, 300
    duSkill()
  }
}

;2,3键,对应面向右,左的后跳踢,或骑马时的面向右,左的后前A技能
Key2(){
  global
  
  if ((mode == MODE_NORMAL) or (mode == MODE_ZHAOYUN)) {
    backJumpKick(FACE_RIGHT)
  } else if (mode == MODE_HORSE) {
    lrSkill(FACE_RIGHT)
  }
}
Key3(){
  global
  
  if ((mode == MODE_NORMAL) or (mode == MODE_ZHAOYUN)) {
    backJumpKick(FACE_LEFT)
  } else if (mode == MODE_HORSE) {
    lrSkill(FACE_LEFT)
  }
}

;右ctrl,转换模式
KeyRControl(){
  global
  
  changeMode(MODE_TOGGLE)
}

;连发拳
KeyW(){
  global
  
  while GetKeyState("w") {
    press(KEY_PUNCH, 30)
    sleep, 20
  }
  return
}

;吃包子
KeyX(){
  global
  
  while GetKeyState("x") {
    eatBread()
    sleep, 20
  }
  return
}

;numpad0,回车暂停
KeyNumpad0(){
  send {enter down}
  sleep, 100
  send {enter up}
}

;numpad1,切换静音
KeyNumpad1(){
  SoundSet, +1, , Mute ;说明书里面的实例,切换静音状态
}

} ;不缩进块

/* 根据游戏平台设置快捷键的函数 
*/ { ;不缩进块
setupHotkeys(title){
  global
  
  local wTitle := "ahk_exe " . title
  if (wTitle == "ahk_exe WinKawaks.exe") { ;模拟器WinKawaks
    Hotkey, IfWinActive, %wTitle%
    Hotkey, ~s, KeyS
    Hotkey, ~q, KeyQ
    HotKey, ~r, KeyR
    HotKey, ~2, Key2
    HotKey, ~3, Key3
    HotKey, ~x, KeyX ;吃包子
    HotKey, ~RControl, KeyRControl
    HotKey, ~Numpad0, KeyNumpad0 ;模拟器暂停
    HotKey, ~Numpad1, KeyNumpad1
    Hotkey, IfWinActive
  } else if (wTitle == "ahk_exe X-Zone.exe") { ;游聚平台
    Hotkey, IfWinActive, %wTitle%
    Hotkey, ~s, KeyS
    Hotkey, ~q, KeyQ
    HotKey, ~r, KeyR
    HotKey, ~2, Key2
    HotKey, ~3, Key3
    HotKey, ~x, KeyX ;吃包子
    HotKey, ~RControl, KeyRControl
    HotKey, ~Numpad1, KeyNumpad1
    HotKey, ~w, KeyW ;增加连发键
    Hotkey, IfWinActive
  }

}

} ;不缩进块

/* 主函数,这里是只显示选择平台的UI,之后交给选择后的函数去处理
*/ { ;不缩进块
main() {
  global

  ;设置游戏平台选择UI
  selectionUI()
}
} ;不缩进块

/* 运行脚本 
*/
main()
return
